﻿using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Options;
using Pay.DTO;
using System.Security.Claims;
using System.Text.Encodings.Web;

namespace Pay.Core
{
	/// <summary>
	/// AuthHandler
	/// </summary>
	public class AuthHandler : AuthenticationHandler<AuthenticationSchemeOptions>
	{
		private readonly PayConfigDto _payConfig;

		/// <summary>
		/// SchemeName
		/// </summary>
		public const string SchemeName = "PayAuth";

		/// <summary>
		/// ctor
		/// </summary>
		public AuthHandler(
			IOptionsMonitor<AuthenticationSchemeOptions> options,
			ILoggerFactory loggerFactory,
			UrlEncoder encoder,
			ISystemClock clock,
			PayConfigDto payConfig)
			: base(options, loggerFactory, encoder, clock)
		{
			_payConfig = payConfig;
		}

		/// <summary>
		/// HandleAuthenticateAsync
		/// </summary>
		protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
		{
			if (Request.Path.HasValue && Request.Path.Value.Contains("/api/pay/"))
			{
				PayRequestDto payReq = null;
                if (Request.HasJsonContentType())
				{
					try
					{
						Request.EnableBuffering();
                        payReq = await Request.ReadFromJsonAsync<PayRequestDto>();
					}
					catch { }
				}

				if (payReq == null)
                    return AuthenticateResult.Fail("支付数据包序列化失败");

                if (!Tool.Data.PayConfigDic.ContainsKey(payReq.PayCategory))
					return AuthenticateResult.Fail($"请先配置好【{payReq.PayCategory.ToDescription()}】相关支付信息:{Request.Protocol}://{Request.Host}");

                var config = Tool.Data.PayConfigDic[payReq.PayCategory];
                if (!config.AppId.Contains(payReq.AppId))
					return AuthenticateResult.Fail($"应用APPID不存在，请先配置好【{payReq.PayCategory.ToDescription()}】相关支付信息:{Request.Protocol}://{Request.Host}");

                return AuthenticateResult.Success(BuildPayTicket(payReq));
			}

			return AuthenticateResult.Success(BuildPayTicket(null));
		}

		#region private methods

		/// <summary>
		/// 生成支付票据
		/// </summary>
		private AuthenticationTicket BuildPayTicket(PayRequestDto payRequest)
		{
			var claims = new List<Claim>();
			if (payRequest != null)
			{
				new Claim("appid", payRequest.AppId);
				var cachePayConfig = Tool.Data.PayConfigDic[payRequest.PayCategory];
				_payConfig.AlipayOption = cachePayConfig.AlipayOption;
				_payConfig.PayCategory = cachePayConfig.PayCategory;
				_payConfig.WeChatPayOption = cachePayConfig.WeChatPayOption;
				_payConfig.WechatPayVersion = string.IsNullOrWhiteSpace(cachePayConfig.WechatPayVersion) ? "V2" : cachePayConfig.WechatPayVersion.ToUpperInvariant();
				_payConfig.ServerIp = cachePayConfig.ServerIp;
				if (payRequest.PayCategory == PayCategoryEnum.AliPay)
					_payConfig.AlipayOption.AppId = payRequest.AppId;
				else if (payRequest.PayCategory == PayCategoryEnum.WechatPay)
					_payConfig.WeChatPayOption.AppId = payRequest.AppId;
			}
			var identity = new ClaimsIdentity(claims, Scheme.Name);
			var principal = new ClaimsPrincipal(identity);
			var ticket = new AuthenticationTicket(principal, Scheme.Name);
			return ticket;
		}

		#endregion private methods
	}
}
